//
//  PSStatistics.m
//  PrefCore
//
//  Created by Sergey on 2/23/14.
//  Copyright (c) 2014 Play-on-smart. All rights reserved.
//

#import "PSStatistics.h"
#import "PSGame.h"

@implementation PSGameStatistics

-(void) add:(PSGameStatistics*)other {
    _played += other.played;
    _pool += other.pool;
    _deleted += other.deleted;
}

@end

@implementation PSSetStatistics

-(void) add:(PSSetStatistics*)other {
    _deals += other.deals;
    _passing += other.passing;
}

@end

@implementation PSAggregationStatistics

-(void) add:(PSAggregationStatistics*)other {
    _sets += other.sets;
    _tricks += other.tricks;
    _success += other.success;
}

@end

@implementation PSPercentage

-(instancetype)initWithTotal:(uint64_t)total andSuccess:(uint64_t)success {
    NSAssert(success <= total, @"Success count cannot exceed the total.");
    if (self = [super init]) {
        _total = total;
        if (_total) {
            _percentageOfSuccess = [NSString stringWithFormat:@"%lld%%", (100*success) / _total];
        } else {
            _percentageOfSuccess = @"0%";
        }
    }
    return self;
}

-(NSString*)description {
    return _percentageOfSuccess;
}

@end

@implementation PSRatio

-(instancetype)initWithX:(uint64_t)x andY:(uint64_t)y {
    if (self = [super init]) {
        _x = x;
        _y = y;
    }
    return self;
}

-(NSString*)description {
    if (!_x || !_y) {
        return [NSString stringWithFormat:@"%lld / %lld", _x, _y];
    }
    double res = (double)_x / _y;
    NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
    [nf setMinimumFractionDigits:2];
    [nf setMaximumFractionDigits:2];
    [nf setMinimumIntegerDigits:1];
    return [nf stringFromNumber:@(res)];
}

@end

@interface PSStatistics () {
    uint64_t _score[PS_GAME_PLAYERS];
    uint64_t _withoutThree[PS_GAME_PLAYERS];
    uint64_t _passes[PS_GAME_PLAYERS];
    uint64_t _passingTricks[PS_GAME_PLAYERS];
    PSAggregationStatistics *_misere[PS_GAME_PLAYERS];
    PSAggregationStatistics *_whists[PS_GAME_PLAYERS];
    PSAggregationStatistics *_tricking[PS_GAME_PLAYERS][PS_BID_MAX-PS_BID_MIN+1];
}

@end

@implementation PSStatistics

-(instancetype)init {
    if (self = [super init]) {
        _games = [[PSGameStatistics alloc] init];
        _sets = [[PSSetStatistics alloc] init];
        for (int i = 0 ; i != PS_GAME_PLAYERS ; i++) {
            for (int j = 0 ; j != PS_BID_MAX-PS_BID_MIN+1 ; j++) {
                _tricking[i][j] = [[PSAggregationStatistics alloc] init];
            }
            _misere[i] = [[PSAggregationStatistics alloc] init];
            _whists[i] = [[PSAggregationStatistics alloc] init];
        }
    }
    return self;
}

-(uint64_t*)score {
    return _score;
}

-(uint64_t*) withoutThree {
    return _withoutThree;
}

-(uint64_t*) passes {
    return _passes;
}

-(uint64_t*) passingTricks {
    return _passingTricks;
}

-(PSAggregationStatistics* __strong *) misere {
    return _misere;
}

-(PSAggregationStatistics* __strong *) whists {
    return _whists;
}
-(void)updateTrickingForPlayerId:(PSPlayerId)playerId
                        contract:(PSTrickCount)contract
                          tricks:(PSTrickCount)tricks {
    PSAggregationStatistics *a = _tricking[playerId][PSGetContractIndex(contract)];
    a.tricks += tricks;
    a.sets++;
    a.success += (tricks >= contract);
}

-(NSArray*)averageScore {
    NSNumber *result[PS_GAME_PLAYERS];
    for (int i = 0; i != PS_GAME_PLAYERS ; i++) {
        result[i] = [NSNumber numberWithLongLong:_games.played ? (_score[i] / _games.played) : 0];
    }
    return [NSArray arrayWithObjects:result count:PS_GAME_PLAYERS];
}

-(uint64_t)numberOfTrickingSets {
    uint32_t res = 0;
    for (int i = 0 ; i != PS_GAME_PLAYERS ; i++) {
        for (int j = 0 ; j != PS_BID_MAX-PS_BID_MIN+1 ; j++) {
            res += _tricking[i][j].sets;
        }
    }
    return res;
}

-(NSArray*)trickingSetResultForContract:(PSTrickCount)contract {
    PSPercentage *res[PS_GAME_PLAYERS];
    for (int i = 0 ; i != PS_GAME_PLAYERS ; i++) {
        PSAggregationStatistics *a = _tricking[i][PSGetContractIndex(contract)];
        res[i] = [[PSPercentage alloc] initWithTotal:a.sets andSuccess:a.success];
    }
    return [NSArray arrayWithObjects:res count:PS_GAME_PLAYERS];
}

-(NSArray*)misereSetResult {
    PSPercentage *res[PS_GAME_PLAYERS];
    for (int i = 0 ; i != PS_GAME_PLAYERS ; i++) {
        PSAggregationStatistics *a = _misere[i];
        res[i] = [[PSPercentage alloc] initWithTotal:a.sets andSuccess:a.success];
    }
    return [NSArray arrayWithObjects:res count:PS_GAME_PLAYERS];
}

-(NSArray*)whistedSets {
    PSPercentage *res[PS_GAME_PLAYERS];
    for (int i = 0 ; i != PS_GAME_PLAYERS ; i++) {
        PSAggregationStatistics *a = _whists[i];
        res[i] = [[PSPercentage alloc] initWithTotal:a.sets andSuccess:a.success];
    }
    return [NSArray arrayWithObjects:res count:PS_GAME_PLAYERS];
}

-(NSArray*)averagePassingTricks {
    NSNumber *res[PS_GAME_PLAYERS];
    for (int i = 0 ; i != PS_GAME_PLAYERS ; i++) {
        res[i] = [NSNumber numberWithDouble:_sets.passing ? (double)_passingTricks[i] / _sets.passing : 0];
    }
    return [NSArray arrayWithObjects:res count:PS_GAME_PLAYERS];
}

-(NSArray*)ratioWhistsToPasses {
    PSRatio *res[PS_GAME_PLAYERS];
    for (int i = 0 ; i != PS_GAME_PLAYERS ; i++) {
        res[i] = [[PSRatio alloc] initWithX:_whists[i].sets andY:_passes[i]];
    }
    return [NSArray arrayWithObjects:res count:PS_GAME_PLAYERS];
}

-(NSString*)description {
    return [NSString stringWithFormat:@"Games: %lld Pool: %lld Score: %lld"
    ,   _numOfGames
    ,   _totalPool
    ,   _totalAmount
    ];
}

-(PSAggregationStatistics*)trickingOfPlayer:(PSPlayerId)playerId forContract:(PSTrickCount)contract {
    return _tricking[playerId][PSGetContractIndex(contract)];
}

@end
